package org.openfans.feed;

import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openfans.domain.FansFeed;
import org.openfans.domain.FansFeedItem;
import org.openfans.domain.Feed;
import org.openfans.domain.FeedItem;
import org.openfans.domain.OthersFeed;
import org.openfans.domain.OthersFeedItem;
import org.openfans.domain.TagFeed;
import org.openfans.domain.TagFeedItem;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class FeedRetriever {
	private static final Log logger = LogFactory.getLog(FeedRetriever.class);

	public List<FeedItem> getFeedItems(Feed feed) {

		try {
			CacheManager cm = CacheManager.create("classpath:ehcache.xml");
			Cache cache = cm.getCache("org.openfans.cache.FeedItem");
			Element e = cache.get(feed.getFeedUrl());

			if (e == null) {
				List<FeedItem> l = getNewFeedItems(feed);
				cache.put(new Element(feed.getFeedUrl(), (Serializable) l));
				return l;
			} else {
				return (List<FeedItem>) e.getValue();
			}
		} catch (Exception e) {
			if (logger.isWarnEnabled()) {
				logger.warn(
						"getFeedItems(Feed) - getFeedItem failed,URL feedUrl="
								+ feed.getFeedUrl(), e);
			}

			return null;
		}
	}

	List<FeedItem> getNewFeedItems(Feed feed) throws Exception {
		List<FeedItem> feedList = new ArrayList<FeedItem>();
		SyndFeed syndFeed = getFeedFromUrl(feed.getFeedUrl());
		List<SyndEntry> l = syndFeed.getEntries();
		for (int i = l.size() - 1; i >= 0; i--) {
			SyndEntry entry = (SyndEntry) l.get(i);
			// }按时间倒排
			// for (SyndEntry entry : l) {
			Date date = entry.getPublishedDate();
			if (null == date) {
				// TODO some nonstandard date string can't be parse
				// with rome，should be use jdom or other parser by hand
			}

			// 只读取新的item
			if (feed.getLastDate().before(date)) {
				FeedItem fi = null;
				// TODO对继承理解不深,先使用instanceof
				if (feed instanceof TagFeed) {
					fi = new TagFeedItem();
					((TagFeedItem) fi).setTag(((TagFeed) feed).getTag());
				} else if (feed instanceof FansFeed) {
					fi = new FansFeedItem();
					((FansFeedItem) fi).setBelongFans(((FansFeed) feed)
							.getBelongFans());
				} else if (feed instanceof OthersFeed) {
					fi = new OthersFeedItem();
				} else {
					fi = new FeedItem();
				}
				fi.setFeed(feed);
				fi.setTitle(entry.getTitle());
				if (logger.isDebugEnabled()) {
					logger.debug("get feed from" + feed.getFeedUrl()
							+ "&&& title is:" + entry.getTitle());
				}

				if (null != entry.getDescription()) {
					fi.setContent(entry.getDescription().getValue());
				}

				fi.setSource(feed.getTitle());
				fi.setAuthor(entry.getAuthor());
				fi.setUrl(entry.getLink());
				fi.setPublishDate(date);
				fi.setFans(feed.getFans());

				feedList.add(fi);
			}
		}
		return feedList;
	}

	private SyndFeed getFeedFromUrl(String url) throws MalformedURLException,
			FeedException, IOException {
		URL feedUrl = new URL(url);
		if (logger.isDebugEnabled()) {
			logger.debug("getFeedItemsDirect(Feed) - URL feedUrl=" + url);
		}
		SyndFeedInput input = new SyndFeedInput();

		SyndFeed syndFeed = input.build(new XmlReader(feedUrl));
		return syndFeed;
	}

	public Feed getFeedInfoFromUrl(String url) throws FeedRetrieveException {

		try {
			SyndFeed sf = getFeedFromUrl(url);
			Feed feed = new Feed();
			feed.setTitle(sf.getTitle());
			feed.setWebUrl(sf.getLink());
			feed.setFeedUrl(url);
			feed.setDescn(sf.getDescription());
			return feed;
		} catch (MalformedURLException e) {
			throw new FeedRetrieveException("url地址格式有误");
		} catch (IOException e) {
			throw new FeedRetrieveException("您确定输入了正确的url地址吗，或者链接现在不可用");
		} catch (FeedException e) {
			throw new FeedRetrieveException("读取feed的内容发生错误");
		}
	}
}

// private static String getFeedUrl(String url){
// URL feedUrl = new URL(url);
// feedUrl.openConnection()
// }}
